package tokenutil

import (
	"fmt"
	"strconv"
	"time"

	"gitee.com/jiebaiyou/formflow/model"
	jwt "github.com/golang-jwt/jwt/v5"
)

// CreateAccessToken 创建访问令牌
// 参数:
//   - user: 用户信息
//   - secret: 令牌签名密钥
//   - expiry: 令牌过期时间(小时)
//
// 返回:
//   - accessToken: 生成的访问令牌
//   - err: 令牌生成过程中的错误
func CreateAccessToken(user *model.User, secret string, expiry int) (accessToken string, err error) {
	claims := &model.JwtCustomClaims{
		Name: user.Name,
		ID:   strconv.FormatUint(uint64(user.ID), 10),
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(expiry))),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	t, err := token.SignedString([]byte(secret))
	if err != nil {
		return "", err
	}
	return t, err
}

// CreateRefreshToken 创建刷新令牌
// 参数:
//   - user: 用户信息
//   - secret: 令牌签名密钥
//   - expiry: 令牌过期时间(小时)
//
// 返回:
//   - refreshToken: 生成的刷新令牌
//   - err: 令牌生成过程中的错误
func CreateRefreshToken(user *model.User, secret string, expiry int) (refreshToken string, err error) {
	claimsRefresh := &model.JwtCustomRefreshClaims{
		ID: strconv.FormatUint(uint64(user.ID), 10),
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(expiry))),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claimsRefresh)
	rt, err := token.SignedString([]byte(secret))
	if err != nil {
		return "", err
	}
	return rt, err
}

// IsAuthorized 验证请求令牌
// 参数:
//   - requestToken: 请求令牌
//   - secret: 令牌签名密钥
//
// 返回:
//   - bool: 是否验证通过
//   - error: 验证过程中的错误
func IsAuthorized(requestToken string, secret string) (bool, error) {
	_, err := jwt.Parse(requestToken, func(token *jwt.Token) (any, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return []byte(secret), nil
	})
	if err != nil {
		return false, err
	}
	return true, nil
}

// ExtractIDFromToken 从请求令牌中提取用户ID
// 参数:
//   - requestToken: 请求令牌
//   - secret: 令牌签名密钥
//
// 返回:
//   - string: 用户ID
func ExtractIDFromToken(requestToken string, secret string) (string, error) {
	token, err := jwt.Parse(requestToken, func(token *jwt.Token) (any, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return []byte(secret), nil
	})
	if err != nil {
		return "", err
	}

	claims, ok := token.Claims.(jwt.MapClaims)

	if !ok && !token.Valid {
		return "", fmt.Errorf("Invalid Token")
	}

	return claims["id"].(string), nil
}
